import 'dart:convert';

import 'package:flutter/foundation.dart';
import 'package:imperius_insights/entity/hr.dart';
import 'package:imperius_insights/entity/project.dart';
import 'package:imperius_insights/entity/quality.dart';
import 'package:imperius_insights/modules/quality/service/buglist.dart'
    as BugList;
import 'package:imperius_insights/modules/scope/domain.dart';
import 'package:imperius_insights/portal/channels/factory.dart';
import 'package:imperius_insights/portal/channels/web.dart';
import 'package:imperius_insights/treaty/endpoint.dart';

const stagingSorts = [
  Staging.Develop,
  Staging.SelfTesting,
  Staging.QATesting,
  Staging.PrePublish,
  Staging.Scheduled,
  Staging.PendingToTest,
  Staging.Unset,
  Staging.Paused,
  Staging.PostPublish,
];

class Service {
  Future<List<Project>> load(
      {@required String departmentId, @required String scopeHumanId}) async {
    final channel = Channels.shared<WebChannel>(ChannelType.Web);
    final params = {
      'param': departmentId,
      'parent': '2',
      'typew': '',
    };
    final response =
        await channel.invoke(target: queryProjectsPlan, params: params);
    final json = jsonDecode(response);
    final nodeData = json['data'];
    final nodeEmployees = nodeData['employees'];
    var projects = List<Project>();
    List employees = nodeEmployees;
    for (dynamic employ in employees) {
      String employName = employ['name'];
      String sysName = employ['rtx_id'];
      humansCache[sysName] = employName;
      if (employName == '姜萌') {
        continue;
      }
//      String employDepartment = employ['department'];
      // plans为该人以天维度的若干天的集合
      List plans = employ['plans'];
      for (dynamic plan in plans) {
        // tasks为该人每天（plan）的任务信息集合
        List tasks = plan['tasks'];
        for (dynamic task in tasks) {
          String pmo = task['name'];
          String projectName = task['title'];
          String priority = task['priority'];
          // 判断是否已经存在（去重）
          if (projects.indexWhere((p) => p.pmo == pmo) >= 0) {
            continue;
          }
          final project =
              Project(name: projectName, pmo: pmo, priority: priority);
          projects.add(project);
        }
      }
    }
    projects = await Future.wait(projects.map((p) => fetchProject(p.pmo)));
    projects.sort((p1, p2) =>
        stagingSorts.indexOf(p1.staging) - stagingSorts.indexOf(p2.staging));
    return projects;
  }

  Future<Project> fetchProject(String pmo) async {
    final project = await fetchSingleProject(pmo);
    final bugListSvc = BugList.Service();
    final bugStats = await bugListSvc.queryOutline(pmo);
    project.qualityInRDTesting = QualityInRDTesting(
      caseTotal: bugStats.caseTotal,
      caseExecuted: bugStats.rdExecutiveCount,
      rdExecutiveRate: bugStats.rdExecutiveRate,
    );
    project.qualityInQATesting = QualityInQATesting(
      caseTotal: bugStats.caseTotal,
      bugRate: bugStats.bugRate,
      caseExecuted: bugStats.rdExecutiveCount,
      rdExecutiveRate: bugStats.rdExecutiveRate,
      bugTotal: bugStats.bugTotal,
      bugOpening: bugStats.bugOpening,
      bugClosed: bugStats.bugClosed,
      rejectedTotal: 0,
      notRdExecutiveCount: bugStats.notRdExecutiveCount,
      notRdExecutiveRate: bugStats.notRdExecutiveRate,
    );
    return project;
  }

  Future<Project> fetchSingleProject(String pmo) async {
    final channel = Channels.shared<WebChannel>(ChannelType.Web);
    final params = {'pmo': pmo};
    final response =
        await channel.invokeForResponse(target: queryPmoInfo, params: params);
    final json = response.data[0];
    final project = Project(pmo: pmo);
    project.name = json['summary'];
    project.startDevDate = tryParseDate(json['expect_start_date']);
    project.parseStaging(json['status']);
    project.type = json['type'];
    project.startTestDate = tryParseDate(json['plan_test_date']);
    project.scheduledPublishDate = tryParseDate(json['plan_release_date']);
    project.actualPublishDate = tryParseDate(json['release_date']);
    project.humansOfRD = _peekHumans(
        json['fe'], (partValue) => HumanRD(getUserName(partValue), partValue));
    project.humansOfRD.addAll(_peekHumans(json['dev'],
        (partValue) => HumanRD(getUserName(partValue), partValue)));
    project.humansOfQA = _peekHumans(
        json['qa'], (partValue) => HumanQA(getUserName(partValue), partValue));
    project.humansOfPM = _peekHumans(
        json['pm'], (partValue) => HumanPM(getUserName(partValue), partValue));
    return project;
  }

  String getUserName(String sysName) {
    return humansCache[sysName] ?? sysName;
  }

  DateTime tryParseDate(String dateStr) {
    final date = DateTime.tryParse(dateStr);
    if (date != null && date.year == 1970) {
      return null;
    }
    return date;
  }

  List<T> _peekHumans<T extends HumanResource>(
      String str, T Function(String partValue) creator) {
    return str
        .split(',')
        .where((partValue) => partValue != "")
        .map((partValue) => creator(partValue))
        .toList(growable: true);
  }
}
